﻿using System;
using System.CodeDom;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
using System.Threading.Tasks;
using MiniExcelLibs;
using Word = Microsoft.Office.Interop.Word;
using Excel = Microsoft.Office.Interop.Excel;
using Microsoft.VisualBasic.ApplicationServices;
using System.Windows.Forms.Integration;
using System.Windows.Interop;

//using Microsoft.VisualBasic.FileIO;

namespace ConsoleApp3_framwork_
{
    internal class Program
    {
        [STAThread]
        private static void Main(string[] args)
        {
            string ExcelprogId = "Excel.Application.16";

            Excel.Application excelApp = (Excel.Application)Activator.CreateInstance(Type.GetTypeFromProgID(ExcelprogId));
            excelApp.Visible = true;
            string WPSprogId = "Ket.Application";

            Excel.Application ETApp = (Excel.Application)Activator.CreateInstance(Type.GetTypeFromProgID(WPSprogId));
            ETApp.Visible = true;

            //var application = new System.Windows.Application();
            //application.Run(new WpfApp1.MainWindow());
            //var win = new WpfApp1.MainWindow();
            //ElementHost.EnableModelessKeyboardInterop(win);
            //var helper = new WindowInteropHelper(win);
            ////helper.Owner=Program.
            //win.Show();

            //var app = new WpfApp1.App();
            //app.InitializeComponent();
            //app.MainWindow = new WpfApp1.MainWindow();
            //app.MainWindow.Show();

            //var app = (Word.Application)Marshal.GetActiveObject("Word.Application");
            //var p = app.ActiveDocument.Paragraphs[1];
            //p.SpaceAfterAuto = 0;
            //p.SpaceBeforeAuto = 0;
            //p.LineUnitAfter = 0;
            //p.LineUnitBefore = 0;
            //p.SpaceAfter = 0;
            //p.SpaceBefore = 0;
            ////p.SpaceAfterAuto = -1;
            ////p.SpaceBeforeAuto = -1;
            //Console.WriteLine(p.Range.Text);
            //Console.WriteLine("");
            Console.Read();
            //Word.Application app = (Word.Application)Marshal.GetActiveObject("Word.Application");
            //Console.WriteLine(app.ActiveDocument.Sections[1].Footers[]);

            /*   Dictionary<string, string> dic = new Dictionary<string, string>();
               var files = System.IO.Directory.GetFiles(@"C:\Users\枸杞\Desktop\就业").ToList();
               files.Remove(@"C:\Users\枸杞\Desktop\就业\苍山街道就业状况待核实名单.xls");
               Excel.Application app = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
               app.ScreenUpdating = false;
               Excel.Worksheet keysh = app.ActiveSheet;
               var n = 0;
               files.ForEach(f =>
               {
                   Console.WriteLine($"{++n}/{files.Count}\t{f}");
                   Excel.Worksheet ws = app.Workbooks.Open(f).Worksheets[1];
                   object[,] arr = ws.UsedRange.Value;
                   ws.Parent.Close();
                   for (int i = 2; i <= arr.GetUpperBound(1); i++)
                   {
                       string item = arr[i, 6]?.ToString();
                       if (!string.IsNullOrWhiteSpace(item))
                       {
                           var key = arr[i, 7].ToString();
                           dic[key] = item;
                       }
                   }
               });
               object[,] brr = keysh.Range["F2:G225"].Value;
               for (int i = 1; i <= brr.GetUpperBound(0); i++)
               {
                   var key = brr[i, 2].ToString();
                   if (dic.ContainsKey(key))
                   {
                       brr[i, 1] = dic[key];
                   }
                   brr[i, 2] = "'" + key;
               }
               keysh.Range["F2:G225"].Value = brr;
               app.ScreenUpdating = true;
            */
            //var f = app.ActiveDocument.Content.Find;
            //var r = f.Replacement;
            //f.ClearFormatting();
            //r.ClearFormatting();
            //r.Font.Color = Word.WdColor.wdColorRed;
            //r.Text = "【";
            //f.Execute("[", Replace: Word.WdReplace.wdReplaceAll);
            //r.ClearFormatting();
            //r.Text = "";
            //f.ClearFormatting();
            //f.Text = "";
            //var l = GetappFromProcess<Excel.Application>();
            //l?.ForEach(e => Console.WriteLine("worksheets.count\t" + e.Worksheets.Count));

            //byte[] rrid = new Guid("{00020400-0000-0000-C000-000000000046}").ToByteArray();
            //Process.GetProcessesByName("winword")
            //        .ToList()
            //        .ForEach(p =>
            //        {
            //            EnumChildWindows(p.MainWindowHandle, EnumChildFunc, out IntPtr handle);
            //            AccessibleObjectFromWindow(handle, 0xFFFFFFF0, rrid, out Word.Window win);
            //            Console.WriteLine(win?.Application.Documents.Count);
            //        });
            //Console.WriteLine("process.MainWindowHandle\t" + p.MainWindowHandle.ToString("X8"));
            //var excellist = new ExcelExtensions.ExcelAppCollection().ToList();
            //excellist.ForEach(e => Console.WriteLine("worksheets.count\t" + e.Worksheets.Count));

            //var applist = getExcelappfromhandle();
            //Console.WriteLine("------------------------------");
            //List<Word.Document> doclist = GetRunningCOMObjectOfType<Word.Document>();
            //Console.WriteLine("doc.count:" + doclist.Count);
            //doclist.ForEach(d => Console.WriteLine($"name:{d.Name}\tApplication.Documents.Count:{d.Application.Documents.Count}"));

            //Console.WriteLine("------------------------------");

            //var applist = GetRunningCOMObjectOfType<Word.Application>();
            //Console.WriteLine("applist.count:" + applist.Count);
            //applist.ForEach(a => Console.WriteLine(a.Documents.Count));

            //Console.WriteLine("------------------------------");

            //var wdlist = doclist.Where(d => d.Application.ActiveDocument == d).Select(d => d.Application).ToList();
            //Console.WriteLine("wdlist.count:" + wdlist.Count);
            //wdlist.ForEach(a => Console.WriteLine(a.Documents.Count));

            //Console.WriteLine("------------------------------");

            //var process = Process.GetProcessesByName("WINWORD").ToList();
            //process.ForEach(p =>
            //{
            //    var WwF窗口句柄 = FindWindowEx(p.MainWindowHandle, IntPtr.Zero, "_WwF", null);
            //    if (FindWindowEx(WwF窗口句柄, IntPtr.Zero, null, null) == IntPtr.Zero) p.Kill();
            //});
            //GetRunningCOMObjectOfType<Word.Document>()
            //    .Where(d => d.Application.ActiveDocument == d)
            //    .Select(d => d.Application)
            //    .ToList()
            //    .ForEach(a => Console.WriteLine(a.Documents.Count));

            //Word.Application app = (Word.Application)Marshal.GetActiveObject("Word.Application");
            //Type type = Type.GetTypeFromProgID("Word.Application");
            //string clsId = type.GUID.ToString().ToUpper();
            //var r = RunningObjectTable.GetRunningCOMObjectByName(clsId);
            //Console.WriteLine(r);
            //var wdapp = new Word.Application();
            //wdapp.Visible = true;
            //var wdapp2 = new Word.Application();
            //wdapp2.Visible = true;
            //var l = GetRunningInstances("Word.application");
            //l.ForEach(wd => Console.WriteLine(((Word.Application)wd).Documents.Count));
            //object excel = null;

            //var moniker = new System.Runtime.InteropServices.ComTypes.Moniker();
            //moniker.BindToStorage(null, null, typeof(System.Runtime.InteropServices.ComTypes.RunningObjectTable).GUID, out object rot);
            //var runningObjects = (System.Runtime.InteropServices.ComTypes.IRunningObjectTable)rot;
            //runningObjects.EnumRunning(out System.Runtime.InteropServices.ComTypes.IEnumMoniker monikerEnumerator);
            //monikerEnumerator.Reset();
            //IntPtr fetchedMonikers = IntPtr.Zero;
            //while (monikerEnumerator.Next(1, new System.Runtime.InteropServices.ComTypes.IMoniker[1], fetchedMonikers) == 0)
            //{
            //    monikerEnumerator.Next(1, new System.Runtime.InteropServices.ComTypes.IMoniker[1], fetchedMonikers);
            //    moniker.GetDisplayName(null, null, out string displayName);
            //    if (displayName.Contains("Excel"))
            //    {
            //        Marshal.BindToMoniker(moniker, null, typeof(object).GUID, out object excelObj);
            //        excel = excelObj;
            //        break;
            //    }
            //}

            //异步删除文件夹();

            //var b = FileSystem.FileExists("");
            //if (b == true)
            //{
            //    Console.WriteLine("");
            //}

            //FileSystem.DeleteFile(@"C:\Users\Administrator\Desktop\删除测试.txt", UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
            //PPT.Shape s;

            //Word.Application app = (Word.Application)Marshal.GetActiveObject("Word.Application");
            //dynamic canvasItems = app.ActiveDocument.Shapes;
            //canvasItems.Add3DModel(@"C:\Users\Administrator\Desktop\Honghu3D.obj");

            Console.Read();
        }

        private static void 判断单元格计算结果错误()
        {
            Excel.Application app = (Excel.Application)Marshal.GetActiveObject("Excel.application");
            // var v = app.Range["A1"].Value;
            var r = app.Range["A1"];
            var v = r.Value;
            var v2 = r.Value2;
            var err = r.Errors[Excel.XlErrorChecks.xlEvaluateToError];
            //var b=Microsoft.VisualBasic.Information.IsError(Microsoft.VisualBasic.c)
            //.Value is Excel.Error;
            //var e = r.Errors.Item[Excel.XlErrorChecks.xlEvaluateToError];
            Console.WriteLine(r.Errors.Item[Excel.XlErrorChecks.xlEvaluateToError].Value);

            var r2 = app.Range["B1"];
            //Console.WriteLine(r2.Errors == null);
            Console.WriteLine(r2.Errors.Item[Excel.XlErrorChecks.xlEvaluateToError].Value);
        }

        private const String MarshalName = "Excel.Application";

        private const String ProcessName = "EXCEL";

        private const String ComClassName = "EXCEL7";

        private delegate Boolean EnumChildCallback(IntPtr hwnd, ref IntPtr lParam);

        [DllImport("Oleacc.dll")]
        private static extern Int32 AccessibleObjectFromWindow(IntPtr hwnd, UInt32 dwObjectID, byte[] riid, out Excel.Window win);

        [DllImport("Oleacc.dll")]
        private static extern Int32 AccessibleObjectFromWindow(IntPtr hwnd, UInt32 dwObjectID, byte[] riid, out Word.Window win);

        [DllImport("User32.dll")]
        private static extern Boolean EnumChildWindows(IntPtr hWndParent, EnumChildCallback lpEnumFunc, out IntPtr lParam);

        [DllImport("User32.dll")]
        private static extern Int32 GetClassName(IntPtr hWnd, StringBuilder lpClassName, Int32 nMaxCount);

        private static Boolean EnumChildFunc(IntPtr hwndChild, ref IntPtr lParam)
        {
            var buf = new StringBuilder(128);
            GetClassName(hwndChild, buf, 128);
            if (buf.ToString() == "_WwG" || buf.ToString() == "EXCEL7")
            {
                lParam = hwndChild;
                return false;
            }
            return true;
        }

        private static List<T> GetappFromProcess<T>()
        {
            var l = new List<T>();
            byte[] rrid = new Guid("{00020400-0000-0000-C000-000000000046}").ToByteArray();
            if (typeof(T) == typeof(Excel.Application))
            {
                Process.GetProcessesByName("excel").ToList()
                .ForEach(p =>
                {
                    EnumChildWindows(p.MainWindowHandle, EnumChildFunc, out IntPtr handle);
                    AccessibleObjectFromWindow(handle, 0xFFFFFFF0, rrid, out Excel.Window win);
                    if (win != null) l.Add((T)win.Application);
                });
            }
            else if (typeof(T) == typeof(Word.Application))
            {
                Process.GetProcessesByName("winword").ToList()
                .ForEach(p =>
                {
                    EnumChildWindows(p.MainWindowHandle, EnumChildFunc, out IntPtr handle);
                    AccessibleObjectFromWindow(handle, 0xFFFFFFF0, rrid, out Word.Window win);
                    if (win != null) l.Add((T)win.Application);
                });
            }
            else
            {
                return default;
            }

            return l;
        }

        //public static List<Excel.Application> getExcelappfromhandle()
        //{
        //    var list = new List<Excel.Application>();
        //    var a = typeof(Excel.Application);
        //    Guid guid = typeof(Excel.Application).GUID;
        //    Process.GetProcessesByName("Excel")
        //        .ToList()
        //        .ForEach(p =>
        //        {
        //            Console.WriteLine("process.MainWindowHandle\t" + p.MainWindowHandle.ToString("X8"));
        //            int handle = 0;
        //            var childhandl = EnumChildWindows(p.MainWindowHandle.ToInt32(), new EnumChildCallback(EnumChildFunc), ref handle);
        //            Console.WriteLine("childhandle\t" + handle.ToString("X8"));
        //            Excel.Application win = null;
        //            AccessibleObjectFromWindow(handle, DW_OBJECTID, guid.ToByteArray(), ref win);
        //            if (win is Excel.Window w) list.Add(w.Application);
        //        });
        //    return list;
        //}

        //private static List<Word.Window> objlist = new List<Word.Window>();
        [DllImport("user32.dll")]
        private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("ole32.dll")]
        private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);

        [DllImport("ole32.dll")]
        public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

        public static List<T> GetRunningCOMObjectOfType<T>()//最好用的
        {
            IRunningObjectTable runningObjectTable = null;
            IEnumMoniker monikerList = null;
            var instances = new List<T>();
            try
            {
                if (GetRunningObjectTable(0, out runningObjectTable) != 0 || runningObjectTable == null)
                {
                    return default;
                }
                runningObjectTable.EnumRunning(out monikerList);
                monikerList.Reset();
                IMoniker[] monikerContainer = new IMoniker[1];
                IntPtr pointerFetchedMonikers = IntPtr.Zero;
                // int counter = 0;
                while (monikerList.Next(1, monikerContainer, pointerFetchedMonikers) == 0)
                {
                    runningObjectTable.GetObject(monikerContainer[0], out object comInstance);
                    if (comInstance is T castedInstance)
                        instances.Add(castedInstance);
                }
            }
            finally
            {
                if (runningObjectTable != null)
                {
                    Marshal.ReleaseComObject(runningObjectTable);
                }

                if (monikerList != null)
                {
                    Marshal.ReleaseComObject(monikerList);
                }
            }
            return instances;
        }

        // Requires Using System.Runtime.InteropServices.ComTypes

        // Get all running instance by querying ROT

        private static List<object> GetRunningInstances(string progId)
        {
            Type type = Type.GetTypeFromProgID(progId);
            string clsId = type.GUID.ToString().ToUpper();
            //Console.WriteLine("GUID:\t" + clsId);
            GetRunningObjectTable(0, out IRunningObjectTable Rot);
            if (Rot == null) return null;
            // get enumerator for ROT entries
            //IEnumMoniker monikerEnumerator = null;
            Rot.EnumRunning(out IEnumMoniker monikerEnumerator);
            if (monikerEnumerator == null) return null;
            monikerEnumerator.Reset();
            List<object> instances = new List<object>();
            IntPtr pNumFetched = new IntPtr();
            IMoniker[] monikers = new IMoniker[1];
            // go through all entries and identifies app instances

            while (monikerEnumerator.Next(1, monikers, pNumFetched) == 0)
            {
                CreateBindCtx(0, out IBindCtx bindCtx);
                if (bindCtx == null) continue;
                monikers[0].GetDisplayName(bindCtx, null, out string displayName);
                Guid IID_IUnknown = Guid.Empty;
                monikers[0].BindToObject(null, null, ref IID_IUnknown, out object comObj);
                //Console.WriteLine(displayName);
                if (displayName.ToUpper().IndexOf(clsId) > 0)
                {
                    Rot.GetObject(monikers[0], out object ComObject);
                    if (ComObject == null) continue;
                    instances.Add(ComObject);
                }
            }
            return instances;
        }

        /// <summary>
        /// Get a snapshot of the running object table (ROT).
        /// </summary>
        /// <returns>A hashtable mapping the name of the object
        //     in the ROT to the corresponding object</returns>

        public static Hashtable GetRunningObjectTable()
        {
            Hashtable result = new Hashtable();

            IntPtr numFetched = new IntPtr();
            IRunningObjectTable runningObjectTable;
            IEnumMoniker monikerEnumerator;
            IMoniker[] monikers = new IMoniker[1];

            GetRunningObjectTable(0, out runningObjectTable);
            runningObjectTable.EnumRunning(out monikerEnumerator);
            monikerEnumerator.Reset();

            while (monikerEnumerator.Next(1, monikers, numFetched) == 0)
            {
                IBindCtx ctx;
                CreateBindCtx(0, out ctx);

                string runningObjectName;
                monikers[0].GetDisplayName(ctx, null, out runningObjectName);

                object runningObjectVal;
                runningObjectTable.GetObject(monikers[0], out runningObjectVal);

                result[runningObjectName] = runningObjectVal;
            }

            return result;
        }

        private static void 异步删除文件夹()
        {
            var sw = new Stopwatch();
            sw.Start();
            var arr = System.IO.Directory.GetDirectories(@"E:\543740964\Image\Group2");
            int i = 0;
            foreach (var a in arr)
            {
                var l = arr.Length;

                Task.Factory.StartNew(() =>
                {
                    System.IO.Directory.Delete(a, true);
                    i += 1;
                    Console.WriteLine($"{i}/{l}\t{sw.Elapsed}\t{a}");
                });
            }
        }

        private static void NewMethod()
        {
            var 结果 = MiniExcel.Query(@"C:\Users\Administrator\Desktop\如何求最大的物品.xlsx", true)
                 .OrderByDescending(x => x.数量)
                 .GroupBy(x => x.物品名)
                 .OrderByDescending(g => g.Take(3).Sum(s => (double)s.数量))
                 .First().Key;
            Console.WriteLine(结果);
            Console.Read();
        }
    }
}